cmake_minimum_required(VERSION 3.10.2 FATAL_ERROR) # Ubuntu 18.04
project(libAEyeSensorSDK)
include(GNUInstallDirs)

set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
set(THREADS_PREFER_PTHREAD_FLAG TRUE)
find_package(Threads REQUIRED)

if (AEYE_SDK_DEV)
    add_definitions(-DAEYE_SDK_DEV)
endif()

# Fix git commands - provide fallback values when not in a git repository
execute_process(
        COMMAND git rev-parse --abbrev-ref HEAD
        WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
        OUTPUT_VARIABLE GIT_BRANCH
        OUTPUT_STRIP_TRAILING_WHITESPACE
        ERROR_QUIET)
if(NOT GIT_BRANCH)
    set(GIT_BRANCH "unknown")
endif()

execute_process(
        COMMAND git log -1 --format=%h
        WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
        OUTPUT_VARIABLE GIT_COMMIT_HASH
        OUTPUT_STRIP_TRAILING_WHITESPACE
        ERROR_QUIET)
if(NOT GIT_COMMIT_HASH)
    set(GIT_COMMIT_HASH "unknown")
endif()

string(TIMESTAMP BUILD_DATE %Y-%m-%d)
configure_file(
        ${PROJECT_SOURCE_DIR}/includeDev/version.h.in
        ${PROJECT_SOURCE_DIR}/includeDev/version.h
)

set(USE_BUNDLED_SPDLOG True CACHE BOOL "Disable to use non-local spdlog static library")
set(BUNDLED_SPDLOG_HO True CACHE BOOL "If using local spdlog, build in header-only mode - fixes some link errors at cost of longer compile times.")

if (NOT USE_BUNDLED_SPDLOG)
    message("Using external spdlog.")
    find_package(spdlog REQUIRED)
    set(AEYE_SPDLOG spdlog::spdlog)
else()
    message("Using bundled spdlog.")
    add_subdirectory(thirdparty/spdlog)
    set_target_properties(spdlog PROPERTIES POSITION_INDEPENDENT_CODE ON)
    # TODO find way to fix underlying link error for python SO
    if (BUNDLED_SPDLOG_HO)
        message("Using header-only spdlog.")
        set(AEYE_SPDLOG spdlog::spdlog_header_only)
    else()
        message("Using statically build spdlog.")
        set(AEYE_SPDLOG spdlog::spdlog)
    endif()
endif()

# Find all .cpp and .hpp files in include and src dirs
file(GLOB HEADERS_PUBLIC ${PROJECT_SOURCE_DIR}/include/*.h ${PROJECT_SOURCE_DIR}/include/*.hpp)
file(GLOB HEADERS_PRIVATE ${PROJECT_SOURCE_DIR}/includeDev/*.hpp ${PROJECT_SOURCE_DIR}/includeDev/*.h)

file(GLOB_RECURSE AEYESENSOR_SDK_LIB_SOURCES
        ${HEADERS_PUBLIC}
        ${HEADERS_PRIVATE}
        ${PROJECT_SOURCE_DIR}/src/*.cpp)

if (NOT AEYE_SDK_DEV)
    LIST(FILTER AEYESENSOR_SDK_LIB_SOURCES EXCLUDE REGEX SensorDev*)
endif()

message("Filtering out swapfiles for AEyeSensorSDK...")
if (CMAKE_VERSION VERSION_GREATER "3.6.0")
    list(FILTER AEYESENSOR_SDK_LIB_SOURCES EXCLUDE REGEX ^\\.)
    list(FILTER AEYESENSOR_SDK_LIB_SOURCES EXCLUDE REGEX \#)
endif()

# Main library
add_library(AEyeSensorSDK STATIC ${AEYESENSOR_SDK_LIB_SOURCES})
target_include_directories(AEyeSensorSDK PUBLIC
        "$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include;${PROJECT_SOURCE_DIR}/includeDev>"
        "$<INSTALL_INTERFACE:include>")

target_link_libraries(AEyeSensorSDK
        PUBLIC Threads::Threads
        PRIVATE "$<BUILD_INTERFACE:${AEYE_SPDLOG}>"
        )

add_library(AEyeSensorSDK_Serialize INTERFACE)
target_include_directories(AEyeSensorSDK_Serialize INTERFACE "extra/serialization")
target_link_libraries(AEyeSensorSDK_Serialize INTERFACE AEyeSensorSDK cereal)

# Fix the generator expression - define NOT_MSVC properly
set(NOT_MSVC "$<NOT:$<CXX_COMPILER_ID:MSVC>>")

target_compile_options(AEyeSensorSDK PRIVATE
        $<${NOT_MSVC}:-Wall -Wextra -Wformat=2 -Wzero-as-null-pointer-constant -Wvla -Werror=vla -Wold-style-cast>
        $<$<CXX_COMPILER_ID:GNU>:-Wlogical-op>
        )
target_compile_options(AEyeSensorSDK PUBLIC
        $<$<CXX_COMPILER_ID:MSVC>:/wd4200 /wd4996 /W3 /EHsc /permissive-> # /Zc:preprocessor>
        )

set_target_properties(AEyeSensorSDK PROPERTIES
        CXX_STANDARD 14
        CXX_STANDARD_REQUIRED ON
        POSITION_INDEPENDENT_CODE ON # needed if this is linked into a shared object
        )

# Add shared library target
add_library(AEyeSensorSDKShared SHARED ${AEYESENSOR_SDK_LIB_SOURCES})
target_include_directories(AEyeSensorSDKShared PUBLIC
        "$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include;${PROJECT_SOURCE_DIR}/includeDev>"
        "$<INSTALL_INTERFACE:include>")

target_link_libraries(AEyeSensorSDKShared
        PUBLIC Threads::Threads
        PRIVATE "$<BUILD_INTERFACE:${AEYE_SPDLOG}>"
        )

target_compile_options(AEyeSensorSDKShared PRIVATE
        $<${NOT_MSVC}:-Wall -Wextra -Wformat=2 -Wzero-as-null-pointer-constant -Wvla -Werror=vla -Wold-style-cast>
        $<$<CXX_COMPILER_ID:GNU>:-Wlogical-op>
        )
target_compile_options(AEyeSensorSDKShared PUBLIC
        $<$<CXX_COMPILER_ID:MSVC>:/wd4200 /wd4996 /W3 /EHsc /permissive-> # /Zc:preprocessor>
        )

set_target_properties(AEyeSensorSDKShared PROPERTIES
        CXX_STANDARD 14
        CXX_STANDARD_REQUIRED ON
        POSITION_INDEPENDENT_CODE ON
        )

install(
        TARGETS AEyeSensorSDK AEyeSensorSDKShared
        EXPORT AEyeSensorSDKConfig
        LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
        ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
        INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
        RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
)

set(CONFIG_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}")
if (AEYE_SDK_DEV)
    install(
            FILES ${HEADERS_PUBLIC} ${HEADERS_PRIVATE}
            DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
    )
else()
    install(
            FILES ${HEADERS_PUBLIC}
            DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
    )
endif()

install(
        EXPORT AEyeSensorSDKConfig
        DESTINATION "${CONFIG_INSTALL_DIR}"
        FILE AEyeSensorSDKConfig.cmake
)